/*
 * Copyright (C) 2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include <stdlib.h>
#include <check.h>
#include "PlanetWars2dRT-core/utils/cstring_functions.h"


START_TEST(test_cstring_equals)
{
  ck_assert(cstring_equals("test", "test"));
  ck_assert(!cstring_equals("test1", "test2"));
  
  char* str1 = malloc(10 * sizeof(char));
  char* str2 = malloc(10 * sizeof(char));
  str1[0] = str2[0] = 'a';
  str1[1] = str2[1] = 'b';
  str1[2] = str2[2] = 'c';
  str1[3] = str2[3] = '\0';
  ck_assert(cstring_equals(str1, str2));
  str1[1] += 1;
  ck_assert(!cstring_equals(str1, str2));
  free(str1);
  free(str2);
}
END_TEST

START_TEST(test_cstring_starts_with)
{
  ck_assert(cstring_starts_with("abcd", "a"));
  ck_assert(cstring_starts_with("abcd", "ab"));
  ck_assert(!cstring_starts_with("abcd", "cd"));
  ck_assert(!cstring_starts_with("abcd", "bc"));
  ck_assert(!cstring_starts_with("abcd", "abcde"));
}
END_TEST

START_TEST(test_cstring_ends_with)
{
  ck_assert(cstring_ends_with("abcd", "d"));
  ck_assert(cstring_ends_with("abcd", "cd"));
  ck_assert(!cstring_ends_with("abcd", "cde"));
  ck_assert(!cstring_ends_with("abcd", "bc"));
  ck_assert(!cstring_ends_with("abcd", "abcde"));
}
END_TEST

START_TEST(test_nb_of_character_of_cstring)
{
  ck_assert_uint_eq(get_nb_of_character_of_cstring("abcde", 'z'), 0);
  ck_assert_uint_eq(get_nb_of_character_of_cstring("abcde", 'a'), 1);
  ck_assert_uint_eq(get_nb_of_character_of_cstring("aacde", 'a'), 2);
  ck_assert_uint_eq(get_nb_of_character_of_cstring("abade", 'a'), 2);
  ck_assert_uint_eq(get_nb_of_character_of_cstring("qbcdq", 'q'), 2);
}
END_TEST

#define TEST_CSTRING_CONTAINS_ONLY_DIGITS(function)	\
  ck_assert(function( "0"));				\
  ck_assert(function( "1"));				\
  ck_assert(function("01"));				\
  ck_assert(function("99"));				\
  ck_assert(function("12"));				\
  ck_assert(function("53"));				\
  ck_assert(function("0123456789"));			\
							\
  ck_assert(!function("0q"));				\
  ck_assert(!function("q0"));				\
  ck_assert(!function("ab"));				\
  ck_assert(!function("  "));

START_TEST(test_cstring_contains_only_digits)
{
  TEST_CSTRING_CONTAINS_ONLY_DIGITS(cstring_contains_only_digits)
}
END_TEST

#define TEST_CSTRING_IS_UINT(function)		\
  TEST_CSTRING_CONTAINS_ONLY_DIGITS(function)	\
  ck_assert(function(" 1"));			\
  ck_assert(function( "+1"));			\
  ck_assert(function("+12"));

START_TEST(test_cstring_is_int)
{
  TEST_CSTRING_IS_UINT(cstring_is_int)
  ck_assert(cstring_is_int("-1"));
}
END_TEST

START_TEST(test_cstring_is_uint)
{
  TEST_CSTRING_IS_UINT(cstring_is_uint);
  ck_assert(!cstring_is_uint("-1"));
}
END_TEST

START_TEST(test_reverse_cstring)
{
  char str1[] = "abc";
  reverse_cstring(str1);
  ck_assert(cstring_equals(str1, "cba"));
  
  char str2[] = "abcd";
  reverse_cstring(str2);
  ck_assert(cstring_equals(str2, "dcba"));
  
  char str3[] = "12345";
  reverse_cstring(str3);
  ck_assert(cstring_equals(str3, "54321"));
  
  char str4[] = "a";
  reverse_cstring(str4);
  ck_assert(cstring_equals(str4, "a"));
  
  char str5[] = "";
  reverse_cstring(str5);
  ck_assert(cstring_equals(str5, ""));
}
END_TEST

START_TEST(test_get_strcpy)
{
  char str[] = "a string";
  char* str2 = get_strcpy(str);
  ck_assert(cstring_equals(str, str2));
  free(str2);
}
END_TEST

START_TEST(test_cstring_ltrim)
{
  char str[] = "  abc  ";
  cstring_ltrim(str, ' ');
  ck_assert(cstring_equals(str, "abc  "));
}
END_TEST

START_TEST(test_cstring_rtrim)
{
  char str[] = "  abc  ";
  cstring_rtrim(str, ' ');
  ck_assert(cstring_equals(str, "  abc"));
}
END_TEST

START_TEST(test_cstring_trim)
{
  char str[] = "  abc  ";
  cstring_trim(str, ' ');
  ck_assert(cstring_equals(str, "abc"));
}
END_TEST


Suite*
cstring_suite(void)
{
  Suite* s = suite_create("Functions for string in C");
  
  TCase* tc_cstring_questions = tcase_create("Questions");
  tcase_add_test(tc_cstring_questions,
		 test_cstring_equals);
  tcase_add_test(tc_cstring_questions,
		 test_cstring_starts_with);
  tcase_add_test(tc_cstring_questions,
		 test_cstring_ends_with);
  tcase_add_test(tc_cstring_questions,
		 test_nb_of_character_of_cstring);
  tcase_add_test(tc_cstring_questions,
		 test_cstring_contains_only_digits);
  tcase_add_test(tc_cstring_questions,
		 test_cstring_is_int);
  tcase_add_test(tc_cstring_questions,
		 test_cstring_is_uint);
  suite_add_tcase(s, tc_cstring_questions);
  
  TCase* tc_cstring_mutators = tcase_create("Mutators");
  tcase_add_test(tc_cstring_mutators,
		 test_reverse_cstring);
  tcase_add_test(tc_cstring_mutators,
		 test_cstring_ltrim);
  tcase_add_test(tc_cstring_mutators,
		 test_cstring_rtrim);
  tcase_add_test(tc_cstring_mutators,
		 test_cstring_trim);
  suite_add_tcase(s, tc_cstring_mutators);
  
  TCase* tc_cstring_others = tcase_create("Others");
  tcase_add_test(tc_cstring_others,
		 test_get_strcpy);
  suite_add_tcase(s, tc_cstring_others);
  
  return s;
}

int
main(void)
{
  size_t number_failed;
  Suite* s;
  SRunner* sr;
  
  s = cstring_suite();
  sr = srunner_create(s);
  
  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);
  
  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
